using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text.RegularExpressions;

using OpenWaves.HtmlEncoding;

namespace OpenWaves
{
    public static partial class Html
    {
        public static string StripTags(string html)
        {
            Contract.Ensures(Contract.Result<string>() != null);

            if (String.IsNullOrEmpty(html))
                return String.Empty;

            return Regex.Replace(html, @"<(.|\n)*?>", string.Empty);
        }

        [Obsolete("Use Encode method taking HtmlEncodeOptions instead of HtmlEncodeFlags as a parameter", true)]
        [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "text")]
        [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "options")]
        public static string Encode(string text, HtmlEncodeFlags options)
        {
            throw new NotImplementedException();
        }

        [Obsolete("Use Encode method taking HtmlEncodeOptions instead of HtmlEncodeFlags as a parameter", true)]
        [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "text")]
        [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "options")]
        [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "maxLength")]
        public static string Encode(string text, HtmlEncodeFlags options, int maxLength)
        {
            throw new NotImplementedException();
        }

        public static string Encode(string text, HtmlEncodeOptions options)
        {
            IHtmlWriter writer = new HtmlWriter(); 
            
            if(options.Contains(HtmlEncodeOptions.WrapLongWords))
                writer = new WordWrappingHtmlWriterDecorator(writer);

            return Encode(text, GetTokenizersFromFlags(options), writer);
        }

        public static string Encode(string text, int maxLength)
        {
            Contract.Requires<ArgumentOutOfRangeException>(maxLength >= 0);

            var writer = new TruncatingHtmlWriterDecorator(new HtmlWriter(), maxLength);
            
            return Encode(text, Enumerable.Empty<ITokenizer>(), writer);
        }

        public static string Encode(string text, HtmlEncodeOptions options, int maxLength)
        {
            Contract.Requires<ArgumentOutOfRangeException>(maxLength >= 0);

            IHtmlWriter writer = new TruncatingHtmlWriterDecorator(new HtmlWriter(), maxLength);

            if (options.Contains(HtmlEncodeOptions.WrapLongWords))
                writer = new WordWrappingHtmlWriterDecorator(writer);
            
            return Encode(text, GetTokenizersFromFlags(options), writer);
        }

        public static string Encode(string text, IEnumerable<ITokenizer> tokenizers, IHtmlWriter writer)
        {
            Contract.Requires<ArgumentNullException>(tokenizers != null);
            Contract.Requires<ArgumentNullException>(writer != null);

            if (text == null)
                return null;

            if (text.Length == 0)
                return String.Empty;

            var tokenizedHtml = HtmlToken.Tokenize(text, tokenizers);
            tokenizedHtml.Render(writer);
            return writer.ToString();
        }

        private static IEnumerable<ITokenizer> GetTokenizersFromFlags(HtmlEncodeOptions options)
        {
            var tokenizers = new List<ITokenizer>();

            if (options.Contains(HtmlEncodeOptions.PreserveFormatting))
            {
                tokenizers.Add(new FormattingTagsTokenizer());
            }
            if (options.Contains(HtmlEncodeOptions.ActivateUrls))
            {
                tokenizers.Add(new UrlTokenizer());
            }
            if (options.Contains(HtmlEncodeOptions.PreserveLineBreaks))
            {
                tokenizers.Add(new LineBreakTokenizer());
            }

            return tokenizers;
        }
    }
}